home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 351-375 / disk_351 / pdc / libsrc.lzh / Make / make.c < prev    next >
C/C++ Source or Header  |  1990-04-19  |  11KB  |  542 lines

  1. /*
  2.  *    make.c - Do the actual making for make
  3.  &    Modified 4/5/89 by LDH to compile under PDC.
  4.  */
  5.  
  6. #ifdef unix
  7. #include <sys/types.h>
  8. #include <sys/stat.h>
  9. #include <sys/errno.h>
  10. #endif
  11. #ifdef eon
  12. #include <sys/stat.h>
  13. #include <sys/err.h>
  14. #endif
  15. #ifdef os9
  16. #include <time.h>
  17. #include <os9.h>
  18. #include <modes.h>
  19. #include <direct.h>
  20. #include <errno.h>
  21. #endif
  22. #ifdef amiga
  23. #include <fcntl.h>
  24. #include <ctype.h>
  25. #include <errno.h>
  26. #include <libraries/dosextens.h>
  27. #include <exec/memory.h>
  28. #include <exec/io.h>
  29. #include <exec/ports.h>
  30. #include <functions.h>
  31. #endif
  32. #include <stdio.h>
  33. #include "h.h"
  34.  
  35.  
  36. /*
  37.  *    Exec a shell that returns exit status correctly (/bin/esh).
  38.  *    The standard EON shell returns the process number of the last
  39.  *    async command, used by the debugger (ugg).
  40.  *    [exec on eon is like a fork+exec on unix]
  41.  */
  42. int
  43. dosh(string, shell)
  44.     char           *string;
  45.     char           *shell;
  46. {
  47.     int             number;
  48.  
  49. #ifdef AZTEC_C
  50.     char           *av[3], *s, *p;
  51.     int             i;
  52.  
  53.     p = s = malloc((unsigned) strlen(string) + 1);
  54.     strcpy(p, string);            /* make a copy of the string */
  55.     i = 0;
  56.     av[0] = gettok(&p);            /* get first argument */
  57.     av[1] = p;                /* get rest of command line */
  58.     av[2] = NULL;
  59.  
  60.     if (fexecv(av[0], av) == -1)
  61.     fatal("couldn't execute command '%s', error return %02x\n",
  62.           av[0], errno);
  63.  
  64.     free(s);
  65.     return number;
  66. #endif
  67.  
  68. #ifndef AZTEC_C       /* Aztec's preproc chokes on defined() */
  69. #if defined(unix) || defined(pdc)
  70.     return system(string);
  71. #endif
  72. #endif
  73.  
  74. #ifdef eon
  75.     return ((number = execl(shell, shell, "-c", string, 0)) == -1) ?
  76.     -1 :            /* couldn't start the shell */
  77.     wait(number);        /* return its exit status */
  78. #endif
  79. #ifdef os9
  80.     int             status, pid;
  81.  
  82.     strcat(string, "\n");
  83.     if ((number = os9fork(shell, strlen(string), string, 0, 0, 0)) == -1)
  84.     return -1;        /* Couldn't start a shell */
  85.     do {
  86.     if ((pid = wait(&status)) == -1)
  87.         return -1;        /* child already died!?!? */
  88.     } while (pid != number);
  89.  
  90.     return status;
  91. #endif
  92. }
  93.  
  94.  
  95. /*
  96.  *    Do commands to make a target
  97.  */
  98. void
  99. docmds1(np, lp)
  100.     struct name    *np;
  101.     struct line    *lp;
  102. {
  103.     bool            ssilent;
  104.     bool            signore;
  105.     int             estat;
  106.     register char  *q;
  107.     register char  *p;
  108.     char           *shell;
  109.     register struct cmd *cp;
  110. #ifdef amiga
  111.     long SetSignal();
  112. #endif
  113.  
  114.  
  115.     if (*(shell = getmacro("SHELL")) == '\0')
  116. #ifdef eon
  117.     shell = ":bin/esh";
  118. #endif
  119. #ifdef unix
  120.     shell = "/bin/sh";
  121. #endif
  122. #ifdef os9
  123.     shell = "shell";
  124. #endif
  125. #ifdef amiga
  126.     shell = NULL;
  127. #endif
  128.  
  129.     for (cp = lp->l_cmd; cp; cp = cp->c_next) {
  130.     strcpy(str1, cp->c_cmd);
  131.     expand(str1);
  132.     q = str1;
  133.     ssilent = silent;
  134.     signore = ignore;
  135.     while ((*q == '@') || (*q == '-')) {
  136.         if (*q == '@')    /* Specific silent  */
  137.         ssilent = TRUE;
  138.         else        /* Specific ignore  */
  139.         signore = TRUE;
  140.         q++;        /* Not part of the command  */
  141.     }
  142.  
  143.     if (!domake)
  144.         ssilent = 0;
  145.  
  146.     if (!ssilent)
  147.         fputs("    ", stdout);
  148.  
  149.     for (p = q; *p; p++) {
  150.         if (*p == '\n' && p[1] != '\0') {
  151.         *p = ' ';
  152.         if (!ssilent)
  153.             fputs("\\\n", stdout);
  154.         } else if (!ssilent)
  155.         putchar(*p);
  156.     }
  157.     if (!ssilent)
  158.         putchar('\n');
  159.  
  160.     if (domake) {        /* Get the shell to execute it  */
  161.         if ((estat = dosh(q, shell)) != 0) {
  162.         if (estat == -1)
  163.             fatal("Couldn't execute %s", shell);
  164.         else {
  165.             printf("%s: Error code %d", myname, estat);
  166.             if (signore)
  167.             fputs(" (Ignored)\n", stdout);
  168.             else {
  169.             putchar('\n');
  170.             if (!(np->n_flag & N_PREC))
  171.                 if (unlink(np->n_name) == 0)
  172.                 printf("%s: '%s' removed.\n", myname, np->n_name);
  173.             exit(estat);
  174.             }
  175.         }
  176.         }
  177. #ifdef amiga
  178.         if ((SetSignal(0L, SIGBREAKF_CTRL_D) & SIGBREAKF_CTRL_D) != 0) {
  179.         fputs("make: abort due to ^D\n", stdout);
  180.         exit(1);
  181.         }
  182. #endif        
  183.     }
  184.     }
  185. }
  186.  
  187.  
  188. docmds(np)
  189.     struct name    *np;
  190. {
  191.     register struct line *lp;
  192.  
  193.  
  194.     for (lp = np->n_line; lp; lp = lp->l_next)
  195.     docmds1(np, lp);
  196. }
  197.  
  198.  
  199. #ifdef os9
  200. /*
  201.  *    Some stuffing around to get the modified time of a file
  202.  *    in an os9 file system
  203.  */
  204. getmdate(fd, tbp)
  205.     struct sgtbuf  *tbp;
  206. {
  207.     struct registers regs;
  208.     static struct fildes fdbuf;
  209.  
  210.  
  211.     regs.rg_a = fd;
  212.     regs.rg_b = SS_FD;
  213.     regs.rg_x = &fdbuf;
  214.     regs.rg_y = sizeof(fdbuf);
  215.  
  216.     if (_os9(I_GETSTT, ®s) == -1) {
  217.     errno = regs.rg_b & 0xff;
  218.     return -1;
  219.     }
  220.     if (tbp) {
  221.     _strass(tbp, fdbuf.fd_date, sizeof(fdbuf.fd_date));
  222.     tbp->t_second = 0;    /* Files are only acurate to mins */
  223.     }
  224.     return 0;
  225. }
  226.  
  227.  
  228. /*
  229.  *    Kludge routine to return an aproximation of how many
  230.  *    seconds since 1980.  Dates will be in order, but will not
  231.  *    be lineer
  232.  */
  233. time_t
  234. cnvtime(tbp)
  235.     struct sgtbuf  *tbp;
  236. {
  237.     long            acc;
  238.  
  239.  
  240.     acc = tbp->t_year - 80;    /* Baseyear is 1980 */
  241.     acc = acc * 12 + tbp->t_month;
  242.     acc = acc * 31 + tbp->t_day;
  243.     acc = acc * 24 + tbp->t_hour;
  244.     acc = acc * 60 + tbp->t_minute;
  245.     acc = acc * 60 + tbp->t_second;
  246.  
  247.     return acc;
  248. }
  249.  
  250.  
  251. /*
  252.  *    Get the current time in the internal format
  253.  */
  254. time(tp)
  255.     time_t         *tp;
  256. {
  257.     struct sgtbuf   tbuf;
  258.  
  259.  
  260.     if (getime(&tbuf) < 0)
  261.     return -1;
  262.  
  263.     if (tp)
  264.     *tp = cnvtime(&tbuf);
  265.  
  266.     return 0;
  267. }
  268. #endif
  269.  
  270.  
  271. /*
  272.  *    Get the modification time of a file.  If the first
  273.  *    doesn't exist, it's modtime is set to 0.
  274.  */
  275. void
  276. modtime(np)
  277.     struct name    *np;
  278. {
  279. #ifdef unix
  280.     struct stat     info;
  281.     int             fd;
  282.  
  283.  
  284.     if (stat(np->n_name, &info) < 0) {
  285.     if (errno != ENOENT)
  286.         fatal("Can't open %s; error %d", np->n_name, errno);
  287.  
  288.     np->n_time = 0L;
  289.     } else
  290.     np->n_time = info.st_mtime;
  291. #endif
  292. #ifdef eon
  293.     struct stat     info;
  294.     int             fd;
  295.  
  296.  
  297.     if ((fd = open(np->n_name, 0)) < 0) {
  298.     if (errno != ER_NOTF)
  299.         fatal("Can't open %s; error %02x", np->n_name, errno);
  300.  
  301.     np->n_time = 0L;
  302.     } else if (getstat(fd, &info) < 0)
  303.     fatal("Can't getstat %s; error %02x", np->n_name, errno);
  304.     else
  305.     np->n_time = info.st_mod;
  306.  
  307.     close(fd);
  308. #endif
  309. #ifdef os9
  310.     struct sgtbuf   info;
  311.     int             fd;
  312.  
  313.  
  314.     if ((fd = open(np->n_name, 0)) < 0) {
  315.     if (errno != E_PNNF)
  316.         fatal("Can't open %s; error %02x", np->n_name, errno);
  317.  
  318.     np->n_time = 0L;
  319.     } else if (getmdate(fd, &info) < 0)
  320.     fatal("Can't getstat %s; error %02x", np->n_name, errno);
  321.     else
  322.     np->n_time = cnvtime(&info);
  323.  
  324.     close(fd);
  325. #endif
  326. #ifdef amiga
  327.     struct FileInfoBlock *fib;
  328.     struct Lock *myLock;
  329.     long ioErr;
  330.  
  331.     fib = (struct FileInfoBlock *) malloc((unsigned) sizeof(struct FileInfoBlock));
  332.     if ((myLock = Lock(np->n_name, ACCESS_READ)) == NULL) {
  333.     if ((ioErr = IoErr()) != ERROR_OBJECT_NOT_FOUND)
  334.         fatal("Can't Lock '%s'; error %3ld", np->n_name, ioErr);
  335.     np->n_time = 0L;
  336.     } else if (!Examine(myLock, fib)) {
  337.     UnLock(myLock);
  338.     fatal("Can't Examine '%s'; error %3ld", np->n_name, IoErr());
  339.     } else {
  340.      np->n_time = fib->fib_Date.ds_Tick/TICKS_PER_SECOND +
  341.          60*fib->fib_Date.ds_Minute + 86400*fib->fib_Date.ds_Days;
  342.         UnLock(myLock);
  343.     }
  344.     free((char *) fib);
  345. #endif
  346.  
  347. }
  348.  
  349.  
  350. /*
  351.  *    Update the mod time of a file to now.
  352.  */
  353. void
  354. touch(np)
  355.     struct name    *np;
  356. {
  357.     char            c;
  358.     int             fd;
  359.  
  360.  
  361.     if (!domake || !silent)
  362.     printf("    touch(%s)\n", np->n_name);
  363.  
  364.     if (domake) {
  365. #ifdef unix
  366.     long            a[2];
  367.  
  368.     a[0] = a[1] = time(0);
  369.     if (utime(np->n_name, &a[0]) < 0)
  370.         printf("%s: '%s' not touched - non-existant\n",
  371.            myname, np->n_name);
  372. #endif
  373. #ifdef eon
  374.     if ((fd = open(np->n_name, 0)) < 0)
  375.         printf("%s: '%s' not touched - non-existant\n",
  376.            myname, np->n_name);
  377.     else {
  378.         uread(fd, &c, 1, 0);
  379.         uwrite(fd, &c, 1);
  380.     }
  381.     close(fd);
  382. #endif
  383. #ifdef os9
  384.     /*
  385.      * Strange that something almost as totally useless as this is easy
  386.      * to do in os9! 
  387.      */
  388.     if ((fd = open(np->n_name, S_IWRITE)) < 0)
  389.         printf("%s: '%s' not touched - non-existant\n",
  390.            myname, np->n_name);
  391.     close(fd);
  392. #endif
  393. #ifdef pdc
  394.     if ((fd = open(np->n_name, O_WRONLY)) < 0)
  395.         printf("%s: '%s' not touched - non-existant\n",
  396.            myname, np->n_name);
  397.     close(fd);
  398. #endif
  399. #ifdef AZTEC_C
  400.     struct MsgPort *task;
  401.     ULONG dateStamp[3];
  402.     struct Lock *lock, *plock;
  403.     UBYTE *pointer;
  404.  
  405.     if(!(pointer= (UBYTE *)AllocMem(64L,MEMF_PUBLIC)))
  406.         fatal("Can't get 64 bytes for pointer");
  407.     if(!(task=(struct MsgPort *)DeviceProc(np->n_name))) {
  408.         printf("%s: can't get MsgPort for '%s'\n", myname, np->n_name);
  409.         FreeMem((void *) pointer, 64L);
  410.         return;
  411.     }
  412.     if(!(lock = Lock(np->n_name,SHARED_LOCK))) {
  413.         printf("%s: '%s' not touched - non-existant\n",
  414.             myname, np->n_name);
  415.         FreeMem((void *) pointer, 64L);
  416.         return;
  417.     }
  418.     plock = ParentDir(lock);
  419.     UnLock(lock);
  420.  
  421.     strcpy((pointer + 1),np->n_name);
  422.     *pointer = strlen(np->n_name);
  423.  
  424.     dos_packet(task, ACTION_SET_DATE, NULL, plock, (ULONG) &pointer[0] >> 2,
  425.         (ULONG) DateStamp(dateStamp), 0L, 0L, 0L);
  426.  
  427.     UnLock(plock);
  428.     FreeMem((void *) pointer, 64L);
  429. #endif
  430.     }
  431. }
  432.  
  433. /*
  434.  * Recursive routine to make a target. 
  435.  */
  436. int
  437. make(np, level)
  438.     struct name    *np;
  439.     int             level;
  440. {
  441.     register struct depend *dp;
  442.     register struct line *lp;
  443.     register struct depend *qdp;
  444.     time_t          dtime = 1, time();
  445.     bool            didsomething = 0;
  446.  
  447.  
  448.     if (np->n_flag & N_DONE)
  449.     return 0;
  450.  
  451.     if (!np->n_time)
  452.     modtime(np);        /* Gets modtime of this file  */
  453.  
  454.     if (rules) {
  455.     for (lp = np->n_line; lp; lp = lp->l_next)
  456.         if (lp->l_cmd)
  457.         break;
  458.     if (!lp)
  459.         dyndep(np);
  460.     }
  461.     if (!(np->n_flag & N_TARG) && np->n_time == 0L)
  462.     fatal("Don't know how to make %s", np->n_name);
  463.  
  464.     for (qdp = (struct depend *) 0, lp = np->n_line; lp; lp = lp->l_next) {
  465.     for (dp = lp->l_dep; dp; dp = dp->d_next) {
  466.         make(dp->d_name, level + 1);
  467.         if (np->n_time < dp->d_name->n_time)
  468.         qdp = newdep(dp->d_name, qdp);
  469.         dtime = max(dtime, dp->d_name->n_time);
  470.     }
  471.     if (!quest && (np->n_flag & N_DOUBLE) && (np->n_time < dtime)) {
  472.         make1(np, lp, qdp);    /* free()'s qdp */
  473.         dtime = 1;
  474.         qdp = (struct depend *) 0;
  475.         didsomething++;
  476.     }
  477.     }
  478.  
  479.     np->n_flag |= N_DONE;
  480.  
  481.     if (quest) {
  482.     long            t;
  483.  
  484.     t = np->n_time;
  485.     time(&np->n_time);
  486.     return t < dtime;
  487.     } else if (np->n_time < dtime && !(np->n_flag & N_DOUBLE)) {
  488.     make1(np, (struct line *) 0, qdp);    /* free()'s qdp */
  489.     time(&np->n_time);
  490.     } else if (level == 0 && !didsomething)
  491.     printf("%s: '%s' is up to date\n", myname, np->n_name);
  492.     return 0;
  493. }
  494.  
  495.  
  496. make1(np, lp, qdp)
  497.     register struct depend *qdp;
  498.     struct line    *lp;
  499.     struct name    *np;
  500. {
  501.     register struct depend *dp;
  502.  
  503.  
  504.     if (dotouch)
  505.     touch(np);
  506.     else {
  507.     strcpy(str1, "");
  508.     for (dp = qdp; dp; dp = qdp) {
  509.         if (strlen(str1))
  510.         strcat(str1, " ");
  511.         strcat(str1, dp->d_name->n_name);
  512.         qdp = dp->d_next;
  513.         free(dp);
  514.     }
  515.     setmacro("?", str1);
  516.     setmacro("@", np->n_name);
  517.     if (lp)            /* lp set if doing a :: rule */
  518.         docmds1(np, lp);
  519.     else
  520.         docmds(np);
  521.     }
  522. }
  523. #ifdef amiga
  524. /*
  525.  * Replace the Aztec-provided time function with one which returns something
  526.  * easy to find and compare, namely the number of seconds since the Amiga's
  527.  * reference date.  This is the same thing returned by modtime() above.
  528.  */
  529. time_t
  530. time(v)
  531.     time_t *v;
  532. {
  533.     long t[3];
  534.  
  535.     DateStamp(t);
  536.     t[0] = t[2]/TICKS_PER_SECOND + 60*t[1] + 86400*t[0];
  537.     if (v)
  538.     *v = t[0];
  539.     return t[0];
  540. }
  541. #endif
  542.